package com.cskaoyan.javase.oop3._0abstract._1basic;

/**
 * 抽象类的定义:
 * 在继承体系中，从祖先类开始，随着一个个子类的定义，子类变得越来越具体，而祖先类则更具有一般性和抽象性。
 * 在这种情况下，为了体现祖先类在设计上的抽象性，我们只将该类作为派生其他类的父类，而不能创建对象实例。
 * 这个时候，这样的类，我们称之为抽象类。
 *
 * 总之,抽象类是在继承层次中处在祖先类位置的一个类,在其他的场景中是几乎不会使用抽象类的
 * 抽象类就是做祖先类用的
 * 祖先类可以不设计为抽象类,但抽象类的使用基本是用于做祖先类.
 * 基于这样的一个使用场景,抽象类在实际开发中是比较少用的,也会比较少定义
 * 我们学习抽象类,不需要深入学习,知道它的语法,知道它是做祖先类用的就够了
 *
 * 抽象类的特点我们主要从以下角度：
 * [修饰符列表] abstract class 类名{
 *     //类体
 * }
 *      1.抽象类的命名特点
 *          首先它是一个类,所以大驼峰
 *          并且为了体现抽象类的特殊性,所以一般抽象类的命名会以"Abstract"或者"Base"开头
 *          我也推荐大家开发中这么做
 *
 *      2.能用哪些修饰符？
 *          首先和普通类一样,访问权限可用的是一样的,要么public 要么默认
 *          final不可用,abstract和final是冲突的
 *
 *      3.成员特点
 *          普通成员
 *          静态成员
 *              以上内容,抽象类和普通类完全一样,普通类能定义,抽象类也一样可以定义
 *          抽象类既然是抽象的,为什么允许定义普通的实现(成员)方法?
 *              既然有这种语法,那么就可以这么做
 *              当抽象类的所有子类都有一个方法,且需要提供一个默认实现
 *              那么这个方法就可以写在抽象类中作为一个成员方法
 *              子类可以选择继承使用,也可以重写,选择的权力在子类手中
 *
 *          构造器
 *              构造器的作用是什么? 是赋值,不是创建对象
 *              所以抽象类不能new对象,和构造器没有必然关系
 *              抽象类虽然自己不能使用构造器赋值,但是可以给子类new对象时使用,用来给抽象类的成员变量赋值
 *
 *              思考:
 *               所有类都有构造器,包括抽象类吗?
 *                  显然是包括的,所有类都有构造器,包括抽象类
 *
 *          代码块
 *              都有,和普通类一样
 *
 *   以上,总结: 抽象类可以定义普通类当中允许定义的一切结构,甚至它还可以定义普通类没有的抽象方法.
 *
 *   思考:
 *       抽象类可不可以没有抽象方法?
 *       显然是可以的,但是抽象类没有抽象方法一般来说是没有意义的,抽象类就应该有抽象方法
 *
 * 抽象方法
 * 语法:
 * [修饰符列表] abstract 返回值类型 方法名(形参列表);
 * 在抽象类中定义抽象方法,如果子类是一个普通类的话
 * 那么就会强制子类来实现这个抽象方法
 * 在这里,抽象方法起到"占位"的作用
 *
 * 什么叫在子类中实现抽象方法?
 * 其实就是方法的重写
 * 这时重写方法和实现方法是一回事,可以采取以下方式:
 *      1.alt + 回车 子类报错的类名处(推荐)
 *      2.采取重写方法的快捷方式
 *      3.alt + insert 选择重写方法
 *
 * 当然,如果是一个抽象类继承抽象类,那么就无需实现抽象方法,当然也可以选择实现
 *
 * 抽象类的子类特点:
 * 抽象类的子类可以有两种情况：
 *      1.普通类，普通类继承抽象类，必须实现所有的抽象方法。
 *      2.抽象类，抽象子类不需要实现抽象方法，抽象子类可以自由选择实现（或实现或不实现）。
 * 抽象类也是类,它仍然要受Java单继承的限制.
 *
 * @since 15:40
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public abstract class AbstractDemo {
    int a;
    private int b;
    static int c;
    static final int D = 20;

    {}
    static {}

    public AbstractDemo() {
    }

    public AbstractDemo(int a, int b) {
        this.a = a;
        this.b = b;
    }

    public int getB() {
        return b;
    }

    public void test(){}
    public static void testStatic(){}

    // 定义抽象方法
    public abstract void testAbstract();
    public abstract void testAbstract2();
}

// Illegal combination of modifiers: 'final' and 'abstract'
// public abstract final class AbstractDemo {
// }
